﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace QQ2564874169.Core.ORM
{
    public static class SqlsExts
    {
        public static int Update<T>(this IDbExecute execute, T model, int? timeout = null) where T : new()
        {
            var idp = typeof(T).GetProperty("id", BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
            if (idp == null)
                throw new NotSupportedException("实体中没有名为ID的属性。");

            var id = idp.GetValue(model);
            if (id == null)
                throw new ArgumentException("ID不能为空。");

            var whereModel = Activator.CreateInstance<T>();
            idp.SetValue(whereModel, id);
            var setModel = Activator.CreateInstance<T>();
            foreach (var p in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                var v = p.GetValue(model);
                if (v != null && p.Name != idp.Name)
                    p.SetValue(setModel, v);
            }
            return execute.Update(setModel, whereModel, timeout);
        }

        public static int SetNull<T>(this IDbExecute execute, T where, params Expression<Func<T, object>>[] sets)
        {
            return execute.SetNull(where, new ChoiceField<T>(sets));
        }

        public static int SetNullBy<T>(this IDbExecute execute, T where, Action<ChoiceField<T>> sets)
        {
            var choice = new ChoiceField<T>();
            sets(choice);
            return execute.SetNull(where, choice);
        }

        public static T GetForUpdate<T>(this IDbEntityQuery query, T where, int? timeout = null) where T : new()
        {
            return query.Get(new SetWhere<T> { eq = where }, timeout);
        }

        public static IEnumerable<T> GetsForUpdate<T>(this IDbEntityQuery query, T where, int? timeout = null) where T : new()
        {
            return query.Gets(new SetWhere<T> { eq = where }, timeout);
        }

        public static IEnumerable<T> Gets<T>(this IDbEntityQuery query, T where) where T : new()
        {
            return query.Gets(new SetWhere<T> { eq = where });
        }

        public static T Get<T>(this IDbEntityQuery query, T where) where T : new()
        {
            return query.Get(new SetWhere<T> { eq = where });
        }

        public static int Count<T>(this IDbEntityQuery query, T where) where T : new()
        {
            return query.Count(new SetWhere<T> { eq = where });
        }

        public static PageResult<T> Pager<T>(this IDbEntityQuery query, PageSet pageSet, T where) where T : new()
        {
            return query.Pager(new SetWhere<T>
            {
                eq = where,
                Skip = (pageSet.Index - 1) * pageSet.Count,
                Take = pageSet.Count
            });
        }
    }
}
